package com.secsbrain.deploy.utils.command;

import com.alibaba.fastjson.JSON;

import com.secsbrain.common.utils.DateTimeUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * 将命令返回数据写入文件策略
 * Created by yangyang.zhang on 2017/7/4.
 */
public class WriteToFileStrategy extends ExecuteStrategyAdapter implements Closeable {

    private BufferedWriter writer;

    private boolean failed;
    private String errMsg;
    private String command;
    private long serial;
    private static final String MINION_NO_CONNECTED = "Minion did not return. [Not connected]";
    private static final String MINION_NO_RESPONSE = "Minion did not return. [No response]";
    private static final String MINION_NO_RESPONSE_ERR_MSG = "Minion响应超时，不能确认是否执行成功，请确认此任务执行情况，手动标记任务状态...";
    private static final String MAVEN_BUILD_FAILURE = "[INFO] BUILD FAILURE";
    private static final String MAVEN_BUILD_FAILURE_ERR_MSG = "Maven打包可能失败，不能确认是否执行成功，请确认此任务执行情况，手动标记任务状态...";
    private static final String DATE_FORMAT = "yyyy年MM月dd日 HH:mm:ss ";

    public WriteToFileStrategy(String pathString, String command, long serial) {
        this.serial = serial;
        this.command = command;
        try {
            Path path = Paths.get(pathString);
            if (!Files.exists(path)) {
                Files.createDirectories(path);
            }
            Path file = Paths.get(path.toString(), String.valueOf(serial));

            this.writer = Files.newBufferedWriter(file,
                    StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
            this.writer.write(DateTimeUtils.parseDateAsString(new Date(), DATE_FORMAT) + "任务ID:[" + serial + "]=======================================>开始执行!");
            this.writer.newLine();
            this.writer.newLine();
            this.writer.flush();
        } catch (IOException e) {
            throw new RuntimeException("创建文件失败！");
        }
    }

    @Override
    public void processLine(String line) {
        try {
            writer.write(line);
            if (!failed) {
                if (StringUtils.contains(line, MINION_NO_RESPONSE) || StringUtils.contains(line, MINION_NO_CONNECTED)) {
                    failed = true;
                    errMsg = MINION_NO_RESPONSE_ERR_MSG;
                } else if (StringUtils.contains(line, MAVEN_BUILD_FAILURE)) {
                    failed = true;
                    errMsg = MAVEN_BUILD_FAILURE_ERR_MSG;
                }
            }
            writer.newLine();
            writer.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void handleResult(Object result) {
        if (failed) {
            /*不确定是否成功，抛出异常,由handleException来处理*/
            failed = false;
            handleException(new RuntimeException(errMsg));
        }
        try {
            if (result instanceof Integer && Integer.parseInt(String.valueOf(result)) == 0) {
                Map<String, Object> data = new HashMap<>();
                data.put("success", true);
                data.put("taskId", serial);
                result = data;
            }
            this.writer.write(DateTimeUtils.parseDateAsString(new Date(), DATE_FORMAT) + "任务ID:[" + serial + "]=======================================>执行结束!");
            writer.newLine();
            writer.newLine();
            writer.write(JSON.toJSONString(result));
            writer.newLine();
            writer.newLine();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close();
        }
    }

    @Override
    public void handleException(Exception e) {
        /* 由业务处理此异常 */
        throw new RuntimeException(e);
    }

    @Override
    public void close() {
        try {
            if (writer != null) {
                writer.write("=====>command:[" + command + "]");
                writer.newLine();
                writer.flush();
                writer.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
